package com.xingfly.security.jwt.filter;

import com.xingfly.security.jwt.model.JwtUser;
import com.xingfly.security.jwt.service.JwtUserDetailsService;
import com.xingfly.security.jwt.util.JwtConstants;
import com.xingfly.security.jwt.util.JwtTokenUtil;
import com.xingfly.service.AccountService;
import com.xingfly.service.JwtService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by SuperS on 2016/12/21.
 */
public class JwtAuthTokenFilter extends OncePerRequestFilter {
    private final Log logger = LogFactory.getLog(this.getClass());
    @Autowired
    private AccountService accountService;

    @Autowired
    private JwtUserDetailsService jwtUserDetailsService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private JwtService jwtService;
    //获取jwt的键 根据键通过request获取Token
//    @Value("${jwt.header}")
    private String tokenHeader = JwtConstants.JWT_TOKEN_HEADER_PARAM;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //获取Token
        String authToken = request.getHeader(this.tokenHeader);
        //解析出Token中的username
        String username = jwtTokenUtil.getUsernameFromToken(authToken);
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            logger.info("开始验证");
            //判断用户传输的Token和登录列表中的Token一样
            String token = jwtService.getToken(accountService.find(username).getId());
            logger.info("username:" + username);
            logger.info("token:" + token);
            if (authToken.equals(token)) {
                logger.info("token 一样");
                //获取用户对象实例
                JwtUser jwtUser = (JwtUser) this.jwtUserDetailsService.loadUserByUsername(username);
                //检查token信息是否正确
                if (jwtTokenUtil.validateToken(authToken, jwtUser)) {
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(jwtUser, null, jwtUser.getAuthorities());
                    //设置
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    logger.info("验证通过" + username + ", 设置 security context");
                    logger.info("token检查通过，登录列表中存在该token");
                    //存储认证信息
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                } else {
                    logger.info("token检查出错");
                }
            } else {
                logger.info("token检查失败，登录列表中不存在该token");
            }
        } else {
            logger.info("未执行验证");
            logger.info("username:" + username);
            logger.info("Authentication:" + SecurityContextHolder.getContext().getAuthentication());
        }
        filterChain.doFilter(request, response);
    }
}
